# _*_ coding: utf-8 _*_
import json
import shutil
import tarfile
from time import sleep

from . import home
from app import db
from app.home.forms import LoginForm, RegistUser, HardwareForm, Hardware_edit, \
    PasswordForm, CommentForm
from app.models import Manufacturer, Hardware, User, TestReview, TestLog
from flask import render_template, url_for, redirect, flash, session, request, \
    make_response, jsonify, abort
from werkzeug.security import generate_password_hash
from functools import wraps
import random
import string
from PIL import Image, ImageFont, ImageDraw
from io import BytesIO
from sqlalchemy import and_
import os
import datetime

dir_server = os.path.dirname(os.path.realpath(__file__))
dir_results = os.path.abspath(os.path.join(dir_server, "../../results"))


def rndColor():
    '''随机颜色'''
    return (
        random.randint(32, 127), random.randint(32, 127),
        random.randint(32, 127))


def gene_text():
    '''生成4位验证码'''
    return ''.join(random.sample(string.ascii_letters + string.digits, 4))


def draw_lines(draw, num, width, height):
    '''划线'''
    for num in range(num):
        x1 = random.randint(0, width / 2)
        y1 = random.randint(0, height / 2)
        x2 = random.randint(0, width)
        y2 = random.randint(height / 2, height)
        draw.line(((x1, y1), (x2, y2)), fill='black', width=1)


def get_verify_code():
    '''生成验证码图形'''
    code = gene_text()
    # 图片大小120×50
    width, height = 120, 50
    # 新图片对象
    im = Image.new('RGB', (width, height), 'white')
    # 字体
    font = ImageFont.truetype('app/static/fonts/arial.ttf', 40)
    # draw对象
    draw = ImageDraw.Draw(im)
    # 绘制字符串
    for item in range(4):
        draw.text(
            (5 + random.randint(-3, 3) + 23 * item, 5 + random.randint(-3, 3)),
            text=code[item], fill=rndColor(), font=font)
    return im, code


@home.route('/code')
def get_code():
    image, code = get_verify_code()
    # 图片以二进制形式写入
    buf = BytesIO()
    image.save(buf, 'jpeg')
    buf_str = buf.getvalue()
    # 把buf_str作为response返回前端，并设置首部字段
    response = make_response(buf_str)
    response.headers['Content-Type'] = 'image/gif'
    # 将验证码字符串储存在session中
    session['image'] = code
    return response


# 登录验证装饰器
def login_required(func):
    @wraps(func)
    def decorated_function(*args, **kwargs):
        # if "user" not in session:  # 验证session
        if session.get('user'):
            return func(*args, **kwargs)
        else:
            return redirect(url_for('home.login'))

    return decorated_function


@home.route('/hardware/add/', methods=["GET", "POST"])
@login_required
def hardware_add():
    forms = HardwareForm()
    if forms.validate_on_submit():
        data = forms.data
        user_id = session.get('user_id', 0)
        hardware_name = data.get("hardwarename")
        hardware_num = Hardware.query.filter_by(user_id=user_id).filter_by(
            hardware=hardware_name).count()
        if hardware_num:
            flash("设备已存在")
            return redirect(url_for("home.hardware_add"))
        data = Hardware(
            hardware=hardware_name,
            user_id=user_id
        )
        db.session.add(data)
        db.session.commit()
        return redirect(url_for("home.get_hardware"))
    return render_template("home/hardware_add.html", form=forms)


@home.route('/hardware/edit/<int:id>', methods=["GET", "POST"])
# @login_required
def hardware_edit(id=None):
    form = Hardware_edit()
    hardware = Hardware.query.get_or_404(id)
    if request.method == "GET":
        form.hardwarename.data = hardware.hardware
    elif form.validate_on_submit():
        data = form.data
        user_id = session.get('user_id', 0)
        hardware_name = data.get("hardwarename")
        hardware_num = Hardware.query.filter_by(user_id=user_id).filter_by(
            hardware=hardware_name).count()
        if hardware_num:
            flash("设备已存在")
            return redirect(url_for("home.hardware_edit", id=id))
        hardware.hardware = hardware_name
        # db.session.add(data)
        db.session.commit()
        return redirect(url_for("home.get_hardware"))
    return render_template("home/hardware_edit.html", form=form)


@home.route("/hardware/del/<int:id>/", methods=["GET"])
# @login_required
def hardware_del(id=None):
    """
    删除硬件设备
    """
    hardware = Hardware.query.get_or_404(id)  # 根据厂商id查找数据
    db.session.delete(hardware)  # 删除数据
    db.session.commit()  # 提交数据
    return redirect(url_for('home.get_hardware', page=1))  # 渲染模板


@home.route("/hardware/job/del/<string:job_name>/", methods=["GET"])
# @login_required
def job_del(job_name=None):
    """
    删除硬件设备
    """
    job = TestLog.query.filter_by(job_name=job_name).first()
    db.session.delete(job)  # 删除数据
    db.session.commit()  # 提交数据
    hardware_name = Hardware.query.filter_by(
        id=job.hardware_id).first().hardware

    user_name = session.get('user', 0)  # 获取用户id
    user = User.query.filter_by(username=user_name).first()
    path = os.path.join(dir_results, user.manufacturer, hardware_name,
                        job_name)
    # path_tar = path + ".tar.gz"
    shutil.rmtree(path)
    # os.remove(path_tar)
    return redirect(url_for('home.get_job', hardware=hardware_name))


@home.route('/uploader/<string:hardware>', methods=['GET', 'POST'])
# @login_required
def upload_file(hardware=None):
    """
    上传文件
    """
    username = session.get('user', 0)  # 获取用户
    user = User.query.filter_by(username=username).first()
    # home.config['UPLOAD_FOLDER'] = os.path.join(dir_results, user.manufacturer)
    path = os.path.join(dir_results, user.manufacturer, hardware)
    # print(path)
    if request.method == 'POST':
        f = request.files['file']
        if not os.path.exists(path):
            os.makedirs(path)
        f.save(os.path.join(path, f.filename))
        file = f.filename.split(".")[0]
        data = TestLog(
            task_id=123,
            job_name=file,
            upload_time=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
            hardware_id=Hardware.query.filter_by(hardware=hardware).first().id
        )
        job_path = os.path.join(path, f.filename)
        tar = tarfile.open(job_path)
        names = tar.getnames()
        for name in names:
            tar.extract(name, path=path)
        tar.close()
        db.session.add(data)
        db.session.commit()
        jactory_path = os.path.join(path, file, "factory.json")

        with open(jactory_path, 'r')as fp:
            json_data = json.load(fp)

            for testcase in json_data:
                if testcase.get('run') == True:
                    name = testcase.get('name')
                    test_result = testcase.get('status')
                    data = TestReview(
                        testcase_name=name,
                        test_result=test_result,
                        create_time=datetime.datetime.now().strftime(
                            '%Y-%m-%d %H:%M:%S'),
                        hardware_id=Hardware.query.filter_by(hardware=hardware).first().id
                    )
                    db.session.add(data)
                    db.session.commit()
        return redirect(url_for("home.get_job", hardware=hardware))
    return render_template("/home/upload.html", hardware=hardware)


@home.route('/hardware/')
@login_required
def get_hardware():
    return render_template('hardware.html')


@home.route('/hardware_list/', methods=['GET', 'POST'])
@login_required
def hardware_list():
    """
    查询硬件信息
    """
    user_id = session.get("user_id")
    hardwares = Hardware.query.filter(user_id == user_id).all()
    return_data = []
    for hardware in hardwares:
        data = {"id": hardware.id,
                "hardware": hardware.hardware,
                "manufacturer": "<a href=\"job/%s\">查看硬件设备日志</a>" % (
                    hardware.hardware),
                "del": "<a onclick=\"return window.confirm('您想删除吗?');\" "
                       "href=\"del/%s\"><img src=\"/static/admin/images/"
                       "del.gif\" \width=\"20\" height=\20\"></a>" % hardware.id,
                "modify": "<a href=\"edit/%s\"><img src=\"/static/admin/images"
                          "/modify.gif\" \width=\"20\" height=\20\"></a>" % hardware.id}
        return_data.append(data)
    return jsonify({'data': return_data})


@home.route('/hardware/job/<string:hardware>', methods=['GET', 'POST'])
# @login_required
def get_job(hardware=None):
    return render_template("home/results.html", hardware=hardware)


@home.route('/hardware/job_list/<string:hardware>', methods=['GET', 'POST'])
# @login_required
def job_list(hardware=None):
    """
    查询job列表
    """
    results = []
    user_name = session.get('user', 0)  # 获取用户id
    user = User.query.filter_by(username=user_name).first()
    hardware_path = os.path.join(dir_results, user.manufacturer, hardware)
    # print(hardware_path)
    return_data = []
    if not os.path.exists(hardware_path):
        return jsonify({'data': return_data})
    for job in next(os.walk(hardware_path))[1]:
        # dir_task = os.path.join(hardware_path, task)
        # results[task] = []
        # for job in next(os.walk(dir_task))[1]:
        results.append(job)
    for job_name in results:
        data = {
            # "taskid": taskid,
            # "job": jobid,
            # "job": "<a href=\"results/%s/%s/%s/%s\">%s</a>" % (
            #     user.manufacturer, hardware, taskid, jobid, jobid),
            "job": "<a href=\"results/%s/%s/%s\">%s</a>" % (
                user.manufacturer, hardware, job_name, job_name),
            "createtime": datetime.datetime.now().strftime(
                '%Y-%m-%d %H:%M:%S'),
            "del": "<a onclick=\"return window.confirm('您想删除吗?');\" "
                   "href=\"del/%s\"><img src=\"/static/admin/images/del.gif\" "
                   "\width=\"20\" height=\20\"></a>" % job_name,
        }
        return_data.append(data)
    # print(return_data)
    return jsonify({'data': return_data})


@home.route('/results/<manu>/<host>/<job>/logs/<name>')
def get_log(manu, host, job, name):
    """
    获取日志
    :param host:
    :param oec_id:
    :param job:
    :param name:
    :return:
    """
    dir_job = os.path.join(dir_results, manu, host, job)
    logpath = os.path.join(dir_job, name + '.log')
    if not os.path.exists(logpath):
        logpath = os.path.join(dir_job, 'job.log')
    try:
        with open(logpath, 'r') as f:
            log = f.read().split('\n')
    except Exception as e:
        abort(404)
    return render_template('home/log.html', name=name, log=log)


@home.route(
    '/hardware/job/results/<string:manu>/<string:hardware>/<string:job_name>')
# @login_required
def get_job_detail(manu, hardware, job_name):
    """
    查询用例日志
    """
    dir_job = os.path.join(dir_results, manu, hardware, job_name)
    json_info = os.path.join(dir_job, 'compatibility.json')
    json_results = os.path.join(dir_job, 'factory.json')
    try:
        with open(json_info, 'r') as f:
            info = json.load(f)
        with open(json_results, 'r') as f:
            results = json.load(f)
    except Exception as e:
        abort(404)
    return render_template('home/job.html', manu=manu, host=hardware,
                           job=job_name,
                           info=info, results=results)


@home.route('/home/get_testreview/')
@login_required
def get_testreview():
    user_name = session.get("username")

    user_obj = User.query.filter(User.username == user_name).first()
    man_obj = Manufacturer.query.filter(
        Manufacturer.manufacturer_name == user_obj.manufacturer).first()
    hardware_obj = Hardware.query.filter(
        Hardware.manufacturer_id == man_obj.id).first()

    return_datas = []
    for data in hardware_obj:
        hardware_name = data.hardware
        testreview_obj = TestReview.query.filter(
            TestReview.hardware_id == data.id)
        for i in testreview_obj:
            return_data = {
                "testcase_name": i.testcase_name,
                # "test_result": data.test_result,
                "review_result": i.review_result,
                "review_comments": i.review_comments,
                "log_path": i.log_path,
                "hardware_name": hardware_name
            }
            return_datas.append(return_data)
    return jsonify({'data': return_datas})


@home.route("/register/", methods=['GET', 'POST'])
def register():
    """
    注册功能
    """
    # if "user_id" in session:
    #     return redirect(url_for("home.index"))
    form = RegistUser()  # 导入注册表单
    if form.validate_on_submit():  # 提交注册表单
        data = form.data  # 接收表单数据
        # 为User类属性赋值
        user = User(
            username=data['username'],
            email=data['email'],
            contractnum=int(data['contractnum']),
            manufacturer=data['manufacturer'],
            password=generate_password_hash(data['password']),
        )
        db.session.add(user)
        db.session.commit()
        flash("注册成功", 'ok')
        return redirect(url_for('home.login'))
    return render_template("/home/register.html", form=form)


@home.route('/login/', methods=['GET', 'POST'])
def login():
    # if "user_id" in session:        # 如果已经登录，则直接跳转到首页
    #     return redirect(url_for("home.index"))
    form = LoginForm()  # 实例化LoginForm类
    if form.validate_on_submit():  # 如果提交
        data = form.data  # 接收表单数据
        # 判断验证码
        if session.get('image').lower() != form.verify_code.data.lower():
            flash('验证码错误', "err")
            return render_template("/home/login.html", form=form)  # 返回登录页
        # 判断用户名是否存在
        user = User.query.filter_by(
            username=data["username"]).first()  # 获取用户信息
        if not user:
            flash("用户名不存在！", "err")  # 输出错误信息
            return render_template("/home/login.html", form=form)  # 返回登录页
        # 判断用户名和密码是否匹配
        if not user.check_password(
                data["password"]):  # 调用check_password()方法，检测用户名密码是否匹配
            flash("密码错误！", "err")  # 输出错误信息
            return render_template("/home/login.html", form=form)  # 返回登录页

        session["user_id"] = user.id  # 将user_id写入session, 后面用户判断用户是否登录
        session["user"] = user.username  # 将user_id写入session, 后面用户判断用户是否登录
        return redirect(url_for("home.index"))  # 登录成功，跳转到首页
    return render_template("/home/login.html", form=form)  # 渲染登录页面模板


@home.route("/home/base/")
def base():
    return render_template('base.html')


@home.route("/index/")
@login_required
def index():
    user = session.get('user')
    return render_template('index.html')


@home.route("/logout/")
def logout():
    session.pop('user', None)
    return redirect(url_for('home.login'))


@home.route("/modify_pwd/", methods=["GET", "POST"])
def modify_pwd():
    form = PasswordForm()
    if form.validate_on_submit():
        data = form.data
        user = User.query.filter_by(username=session["user"]).first()
        from werkzeug.security import generate_password_hash
        user.password = generate_password_hash(data["password"])
        db.session.add(user)
        db.session.commit()
        return "<script>alert('密码修改成功');location.href='/index';</script>"
    return render_template("home/modify_password.html", form=form)


@home.route("/review_hardware/")
def review_hardware():
    return render_template("home/hardware_list.html")


@home.route("/review_hardware_list/")
def review_hardware_list():
    user_id = session.get("user_id")
    hardwares = Hardware.query.filter(
        Hardware.user_id == user_id).all()
    return_data = []
    for hardware in hardwares:
        data = {
            "hardware": hardware.hardware,
            "review_result": "<a href=\"review_comment/%s\">点击查看详细信息</a>" % hardware.id
        }
        return_data.append(data)
    return jsonify({'data': return_data})


@home.route("/review_hardware/review_comment/<string:hardware_id>")
def review_comment(hardware_id):
    return render_template("home/testcase_review.html",
                           hardware_id=hardware_id)


@home.route("/review_comment_list/<string:hardware_id>")
def review_comment_list(hardware_id):
    testcases = TestReview.query.filter_by(hardware_id=hardware_id).filter_by(
        pid=None)
    return_data = []
    for testcase in testcases:
        testcase_id = testcase.id
        data = {
            "testcase": testcase.testcase_name,
            "review_result": testcase.review_result,
            "review_comment": "<a href=\"http://127.0.0.1:5000/comment/%s/%s/\">点击查看详细信息</a>" % (
                testcase_id, hardware_id)
        }
        return_data.append(data)

    return jsonify({'data': return_data})


@home.route("/comment/<string:testcase_id>/<string:hardware_id>/",
            methods=["GET", "POST"])
def comment(testcase_id, hardware_id):
    """获取评论，提交评论"""
    testcases = TestReview.query.get(int(testcase_id))
    sub_com = TestReview.query.filter_by(pid=int(testcase_id))
    user_name = session.get("user")

    form = CommentForm()
    if form.validate_on_submit():
        data = form.data
        content = data.get("comment")
        data = TestReview(
            testcase_name=testcases.testcase_name,
            review_comments=content,
            pid=testcase_id,
            create_time=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        )
        db.session.add(data)
        db.session.commit()
        return "<script>location.href='/comment/%s/%s/';</script>" % (
            testcase_id, hardware_id)

    return render_template("home/comment.html", testcases=testcases,
                           hardware_id=hardware_id, sub_com=sub_com,
                           user_name=user_name, testcase_id=testcase_id,
                           form=form)


@home.route(
    "/comment_del/<string:review_2_id>/<string:testcase_id>/<string:hardware_id>/")
def comment_del(review_2_id, testcase_id, hardware_id):
    """删除评论"""
    review = TestReview.query.get(int(review_2_id))
    db.session.delete(review)
    db.session.commit()
    return "<script>location.href='http://127.0.0.1:5000/comment/%s/%s';</script>" % (
        testcase_id, hardware_id)
